﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.ServiceModel;
using Peer;

namespace PeerForm
{
    public partial class Watcher : Form
    {
        private string Usuario = string.Empty;
        private string BasePath = string.Empty;
        private IPeerChannel participant;
        private DuplexChannelFactory<IPeerChannel> factory;
        private PeerImplementation peer;

        private delegate void adicionaItemNaListaHandler(string strVal);

        public Watcher()
        {
            InitializeComponent();                      
        }

        public void UpdateScreen(object sender, EventArgs e)
        {
            EventUpdateScreenArgs arg = e as EventUpdateScreenArgs;
            adicionaItemNaLista(arg.Action);
            atualizarListaArquivos();
        }

        public void Sync(object sender, EventArgs e)
        {
            ResponseSyncEventArgs arg = e as ResponseSyncEventArgs;
            participant.ResponseSync(arg.Target);

            foreach (string name in Directory.GetFiles(BasePath))
            {                
                CreateMessage msg = new CreateMessage()
                {
                    Metadata = new FileMetaData(Path.GetFileName(name)),
                    id = Usuario,
                    FileByteStream = new FileStream(name, FileMode.Open)
                };
                this.participant.Create(msg);
                msg.FileByteStream.Close();
                
            }

        }
        
        private void fileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e)
        {

            if (e.ChangeType == WatcherChangeTypes.Changed)
            {

                ChangeMessage msg = new ChangeMessage()
                {
                    NewMetadata = new FileMetaData(e.Name),
                    id = Usuario,
                    FileByteStream = new FileStream(e.FullPath, FileMode.Open)
                };
                participant.Change(msg);

                msg.FileByteStream.Close();

                adicionaItemNaLista("Alteração do arquivo " + e.Name);
                atualizarListaArquivos();

            }
            else if (e.ChangeType == WatcherChangeTypes.Created)
            {

                CreateMessage msg = new CreateMessage()
                {
                    Metadata = new FileMetaData(e.Name),
                    id = Usuario,
                    FileByteStream = new FileStream(e.FullPath, FileMode.Open)
                };
                participant.Create(msg);
                msg.FileByteStream.Close();

                adicionaItemNaLista("Criação do arquivo " + e.Name);
                atualizarListaArquivos();

            }
            else if (e.ChangeType == WatcherChangeTypes.Deleted)
            {

                DeleteMessage msg = new DeleteMessage()
                {
                    DeletedMetadata = new FileMetaData(e.Name),
                    id = Usuario
                };
                participant.Delete(msg);

                adicionaItemNaLista("Exclusão do arquivo " + e.Name);
                atualizarListaArquivos();
            }
         
        }             

        private void fileSystemWatcher1_Renamed(object sender, System.IO.RenamedEventArgs e)
        {
            if (e.ChangeType == WatcherChangeTypes.Renamed)
            {
                RenameMessage msg = new RenameMessage()
                {
                    NewMetadata = new FileMetaData(e.Name),
                    OldMetadata = new FileMetaData(e.OldName),
                    id = Usuario,
                    FileByteStream = new FileStream(e.FullPath, FileMode.Open)
                };
                participant.Rename(msg);
                msg.FileByteStream.Close();

                adicionaItemNaLista("Renomeação de " + e.OldName + " para " + e.Name);
                atualizarListaArquivos();

            }
        }

        private void btnDiretorio_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            DialogResult result = fbd.ShowDialog();

            if (result == DialogResult.OK)
            {
                txtBasePath.Text = fbd.SelectedPath;
                fileWatcher.Path = txtBasePath.Text;
                atualizarListaArquivos();
            }
        }

        private void atualizarListaArquivos()
        {
            listArquivos.Items.Clear();
            
            String[] list = Directory.EnumerateFiles(fileWatcher.Path).ToArray<String>();
            list = list.Select<string, string>(c => Path.GetFileName(c)).ToArray<string>();
            listArquivos.Items.AddRange(list);
          
        }

        private void adicionaItemNaLista(string strVal)
        {
            if (listMudancas.InvokeRequired)
                listMudancas.Invoke(new adicionaItemNaListaHandler(adicionaItemNaLista), new object[] { strVal });
            else
                listMudancas.Items.Add(strVal);
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            if (pcbSync.Visible)
            {
                pcbSync.Visible = false;
                pcbStop.Visible = true;
                fileWatcher.EnableRaisingEvents = true;
                txtBasePath.Enabled = false;
                txtNome.Enabled = false;
                btnDiretorio.Enabled = false;

            }
            else
            {
                pcbSync.Visible = true;
                pcbStop.Visible = false;
                fileWatcher.EnableRaisingEvents = false;
                txtBasePath.Enabled = true;
                btnDiretorio.Enabled = true;
                txtNome.Enabled = true;

            }          

            Usuario = string.IsNullOrEmpty(txtNome.Text) ? "Default" : txtNome.Text;
            BasePath = string.IsNullOrEmpty(txtBasePath.Text) ? @"c:\DropBox" : txtBasePath.Text;

            if (pcbStop.Visible)
                RunConfigurationPeer();
            else
                ClosePeer();
                    
        }

        private void RunConfigurationPeer()
        {
            peer = new PeerImplementation(Usuario, BasePath, fileWatcher);
            peer.UpdateScreen += new EventHandler(this.UpdateScreen);
            peer.SyncEvent += new EventHandler(this.Sync);

            InstanceContext instanceContext = new InstanceContext(peer);
            
            factory = new DuplexChannelFactory<IPeerChannel>(instanceContext, "PeerEndpoint");

            participant = factory.CreateChannel();
            
            IOnlineStatus ostat = participant.GetProperty<IOnlineStatus>();          

            try
            {

                participant.Open();

            }
            catch (CommunicationException)
            {
                Console.WriteLine("Could not find resolver.  If you are using a custom resolver, please ensure");
                Console.WriteLine("that the service is running before executing this sample.  Refer to the readme");
                Console.WriteLine("for more details.");
                return;
            }

            participant.Sync(Usuario);

            
        }       

        public void ClosePeer()
        {
            // Leave the mesh
            //participant.Leave(member);
            if (participant != null)
            {
                participant.Close();
                factory.Close();
            }
        }
    }
}
